﻿/*
 *	Copyright (c) 2009 Queensland University of Technology. All rights reserved.
 *	The QUT Bioinformatics Collection is open source software released under the 
 *	Microsoft Public License (Ms-PL): http://www.microsoft.com/opensource/licenses.mspx.
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using QUT.Bio.Util;
using NCBI_Eutils.Eutils;

namespace BlastExplorer {
	/// <summary>
	/// Interaction logic for BasicGenbankDisplay.xaml
	/// </summary>
	public partial class BasicGenbankDisplay : UserControl {
		Style nameStyle;
		Style valueStyle;
		const int sequenceNameColumn = 0;
		const int sequenceNameColspan = 3;
		const int sequenceValueColumn = 4;
		const int sequenceValueColspan = 3;
		
		const int nestedSequenceNameColumn = 1;
		const int nestedSequenceNameColspan = 2;
		
		const int featureNameColumn = 2;
		const int featureNameColspan = 1;
		
		const int qualifierNameColumn = 4;
		const int qualifierNameColspan = 1;
		const int qualifierValueColumn = 6;
		const int qualifierValueColspan = 1;

		public BasicGenbankDisplay (
			GBSeqType gbSeq
		) {
			InitializeComponent();
			
			nameStyle = (Style) Resources["Head"];
			valueStyle = (Style) Resources["Text"];

			AddSequenceAttributes( gbSeq );
			AddFeatureAttributes( gbSeq );
		}

		private void AddSequenceAttributes ( GBSeqType gbSeq ) {
			AddAttribute( "Locus", gbSeq.GBSeq_locus );
			AddAttribute( "Definition", gbSeq.GBSeq_definition );
			AddAttribute( "Accession", gbSeq.GBSeq_accessionversion );
			AddAttribute( "Source", gbSeq.GBSeq_source + " (" + gbSeq.GBSeq_sourcedb + ")" );
			
			AddReferences( gbSeq.GBSeq_references );
			
			AddAttribute( "Comment", gbSeq.GBSeq_comment );
		}
	
		private void AddReferences ( GBReferenceType [] references ) {
			if ( references != null ) {
			foreach ( GBReferenceType reference in references ) {
				AddAttribute( "Reference", reference.GBReference_position );
				AddNestedAttribute( "Authors", 
					reference.GBReference_authors == null ? "" : 
					reference.GBReference_authors.Join(",") 
				);
				AddNestedAttribute( "Title", reference.GBReference_title );
				AddNestedAttribute( "Journal", reference.GBReference_journal );
				AddPubmed( reference.GBReference_pubmed );
				AddNestedAttribute( "Remark", reference.GBReference_remark );
			}
			}
		}

		private void AddFeatureAttributes ( GBSeqType gbSeq ) {
			if ( gbSeq.GBSeq_featuretable != null ) {
				foreach ( GBFeatureType feature in gbSeq.GBSeq_featuretable ) {
					AddFeatureHeading( feature.GBFeature_key, feature.GBFeature_location );
					
					foreach ( GBQualifierType qualifier in feature.GBFeature_quals ) {
						if ( qualifier.GBQualifier_name == "db_xref" ) {
							AddXref( qualifier.GBQualifier_value );
						}
						else {
							AddQualifier( qualifier.GBQualifier_name, qualifier.GBQualifier_value );
						}
					}
				}
			}
		}

		public TextBlock TextField ( string s, Style style, int column, int colspan ) {
			TextBlock textBlock = new TextBlock {
				Style = style,
				Text = s
			};

			textBlock.SetColumn( column );
			textBlock.SetColumnSpan( colspan );

			return textBlock;
		}

		public XrefHyperlink Xref ( string database, string id, Uri address, int column, int colspan ) {
			XrefHyperlink result = new XrefHyperlink{
				Database = database,
				Id = id,
				Address = address,
				Style = null
			};
			
			result.SetColumn( column );
			result.SetColumnSpan( colspan );
			
			return result;
		}
		
		public void AddAttribute( string name, string value ) {
			TextBlock nameField = TextField( name, nameStyle, sequenceNameColumn, sequenceNameColspan );
			TextBlock valueField = TextField( value, valueStyle, sequenceValueColumn, sequenceValueColspan );
			grid.AddRow( nameField, valueField );
		}
		
		public void AddNestedAttribute ( string name, string value ) {
			TextBlock nameField = TextField( name, nameStyle, nestedSequenceNameColumn, nestedSequenceNameColspan );
			TextBlock valueField = TextField( value, valueStyle, sequenceValueColumn, sequenceValueColspan );
			grid.AddRow( nameField, valueField );
		}
		
		public void AddFeatureHeading( string featureName, string location ) {
			TextBlock nameField = TextField( featureName, nameStyle, featureNameColumn, featureNameColspan );
			TextBlock valueField = TextField( location, valueStyle, qualifierValueColumn, qualifierValueColspan );
			grid.AddRow( nameField, valueField );
		}

		public void AddQualifier ( string name, string value ) {
			TextBlock nameField = TextField( name, nameStyle, qualifierNameColumn, qualifierNameColspan );
			TextBlock valueField = TextField( value, valueStyle, qualifierValueColumn, qualifierValueColspan );
			grid.AddRow( nameField, valueField );
		}

		public void AddXrefQualifier ( string database, string id, Uri address ) {
			TextBlock nameField = TextField( "db_xref", nameStyle, qualifierNameColumn, qualifierNameColspan );
			XrefHyperlink hyperlink = Xref( database, id, address, qualifierValueColumn, qualifierValueColspan );
			grid.AddRow( nameField, hyperlink );
		}

		public void AddPubmed ( string id ) {
			Uri address = new Uri( String.Format( "http://www.ncbi.nlm.nih.gov/pubmed/{0}", id ) );
			XrefHyperlink hyperlink = Xref( "PUBMED", id, address, sequenceValueColumn, sequenceValueColspan );
			grid.AddRow( hyperlink );
		}
		
		public void AddXref( string qualifierValue ) {
			string [] parts = qualifierValue.Split( ':' );
			string database = parts[0];
			string id = parts[1];
			Uri address = null;
			
			if ( database == "taxon" ) {
				address = new Uri( string.Format(
					"http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?id={0}",
					id
				) );
			}
			else if ( database == "CDD" ) {
				address = new Uri( string.Format(
					"http://www.ncbi.nlm.nih.gov/Structure/cdd/cddsrv.cgi?uid={0}",
					id
				) );
			}
			
			if ( address != null ) {
				AddXrefQualifier( database, id, address );
			}
			else {
				AddQualifier( "db_xref", qualifierValue );
			}
		}
	}
}
